package com.franklin.validation.core;


import com.franklin.validation.core.annotations.NotNullForMap;
import com.franklin.validation.core.annotations.RequestParamRule;
import com.franklin.validation.core.annotations.Response;
import com.franklin.validation.core.constants.Constants;
import com.franklin.validation.core.entity.CheckJsonEntity;
import com.franklin.validation.core.interfaces.Rule;
import com.franklin.validation.core.response.JsonResponse;
import com.franklin.validation.core.utils.DataCheckUtil;
import com.franklin.validation.core.utils.ReflectionUtil;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * Description :
 * Create By: Franklin
 * Date : 2020/6/1 15:45
 */
@Component
public class RequestParamRuleFactory extends AbstractRuleFactory<CheckJsonEntity,String,RequestParamRule> implements JsonResponse<String,Object> {

    private Map<Class,JsonResponse> responseMap;

    @PostConstruct
    public void init(){
        super.init();
        Map<String,Rule> ruleMap = new HashMap<>(this.ruleMap.size());
        this.ruleMap.forEach((k,v) -> {
            RequestParamRule annotation = v.getClass().getDeclaredAnnotation(RequestParamRule.class);
            ruleMap.put(annotation.version(),v);
        });
        this.ruleMap.clear();
        this.ruleMap = ruleMap;
        Map<String, Object> beansWithAnnotation = this.applicationContext.getBeansWithAnnotation(Response.class);
        this.responseMap = new HashMap<>(beansWithAnnotation.size());
        Map<Boolean, List<Map.Entry<String, Object>>> isDefaultMap = beansWithAnnotation.entrySet()
                .stream()
                .collect(Collectors.groupingBy(entry -> entry.getKey().startsWith(Constants.DEFAULT)));
        isDefaultMap.get(true).forEach(this::setBean);
        List<Map.Entry<String, Object>> notDefaultList = isDefaultMap.get(false);
        if (DataCheckUtil.isNotEmpty(notDefaultList)){
            notDefaultList.forEach(this::setBean);
        }
    }

    private void setBean(Map.Entry<String, Object> entry) {
        Response response = entry.getValue().getClass().getDeclaredAnnotation(Response.class);
        this.responseMap.put(response.type(),(JsonResponse) entry.getValue());
    }

    @Override
    public String check(CheckJsonEntity input) {
        try {
            NotNullForMap notNullForMap = input.getNotNullForMap();
            Rule<Object,String> rule = this.ruleMap.get(notNullForMap.version());
            return rule.check(input);
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    @Override
    public Object getResponse(String input,Class type){
        return this.responseMap.get(type).response(input);
    }

    @Override
    public Object defaultResponse(Class ... type) {
        return this.responseMap.get(type[0]).defaultResponse();
    }
}
